package com.gouda.core.service.impl.systemManage;

import com.themis.constant.FrontConstant;
import com.themis.dao.SystemUserRoleDao;
import com.themis.dto.BackendSystemUserDto;
import com.themis.dto.FrontFunctionDto;
import com.themis.dto.SystemUserDto;
import com.themis.entity.SystemFunctionEntity;
import com.themis.enums.EnumIsDefaultPassword;
import com.themis.enums.EnumIsEnable;
import com.themis.enums.EnumSystemUserType;
import com.themis.service.BaseService;
import com.themis.service.SystemFunctionService;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.gouda.core.dao.SystemUserDao;
import com.gouda.core.entity.SystemUserEntity;
import com.gouda.core.service.systemManage.SystemUserService;
import com.hephaestus.utils.DataUtil;
import com.hephaestus.utils.Md5;
import lombok.extern.slf4j.Slf4j;
import org.amethyst.atlas.basic.component.PageData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * Created by KGL on 2015/8/13.
 */
@Service
@Slf4j
public class SystemUserServiceImpl extends BaseService implements SystemUserService {

    @Autowired
    private SystemUserDao userDao;
    @Autowired
    private SystemUserRoleDao userRoleDao;
    @Autowired
    private SystemFunctionService functionService;

    @Override
    public PageData<SystemUserDto> loadUsersByPrivilege(final String loginUserId, final String userCode, final String userName, final String userStatus, final String pageNum) {
        SystemUserEntity loginUser = getLoginUser(loginUserId);
        final String userType = loginUser.getUserType()+"";
        final int count = userDao.seekUserCountByPrivilege(userType, userCode, userName, userStatus);
        if (count <= 0) {
            return null;
        }
        int queryPageNum = FrontConstant.DEFAULT_START_PAGE;
        if (!Strings.isNullOrEmpty(pageNum)) {
            queryPageNum = Integer.valueOf(pageNum);
        }
        PageData<SystemUserDto> pageData = new PageData<>(count, queryPageNum, FrontConstant.DEFAULT_PAGE_SIZE);
        List<SystemUserEntity> userList = userDao.seekUsersByPrivilege(userType, userCode, userName, userStatus, pageData.getSqlStart(), pageData.getRowsPerPage());
        pageData.setData(this.generateDtos(userList));
        return pageData;
    }

    private SystemUserEntity getLoginUser(final String loginUserId){
        SystemUserEntity userEntityProxy = ENTITY_FACTORY.generateDBEntity(SystemUserEntity.class);
        userEntityProxy.setUserId(Long.valueOf(loginUserId));
        return userDao.unique(userEntityProxy);
    }

    @Override
    public void modifyUser(final String loginUserId, final String userId, final String userName, final String userPassword, final String userStatus) {
        SystemUserEntity proxyEntity = ENTITY_FACTORY.generateDBEntity(SystemUserEntity.class);
        proxyEntity.setUserId(Long.valueOf(userId));

        SystemUserEntity userEntity = userDao.unique(proxyEntity);
        boolean updateFlag = false;
        if (!Strings.isNullOrEmpty(userName)){
            userEntity.setUserName(userName);
            updateFlag = true;
        }
        if (!Strings.isNullOrEmpty(userPassword)){
            userEntity.setUserPassword(Md5.GetMD5Code(userPassword));
            userEntity.setDefaultPassword(EnumIsDefaultPassword.NO.getCode());
            updateFlag = true;
        }
        if (!Strings.isNullOrEmpty(userStatus)){
            userEntity.setUserStatus(Integer.valueOf(userStatus));
            updateFlag = true;
        }
        if (updateFlag){
            SystemUserEntity loginUser = this.getLoginUser(loginUserId);
            userEntity.setModifier(loginUser.getUserName());
            userEntity.setModifyTime(new Date());
            userDao.update(userEntity);
        }
    }

    @Override
    public boolean checkExist(final String userCode) {
        boolean checkFlag = false;
        List<SystemUserEntity> resultList = userDao.seekByUserCode(userCode);
        if (!resultList.isEmpty()) checkFlag = true;
        return checkFlag;
    }

    @Override
    public void addUser(final String loginUserId, final String userCode, final String userName) {

        SystemUserEntity loginUser = this.getLoginUser(loginUserId);

        SystemUserEntity user = ENTITY_FACTORY.generateDBEntity(SystemUserEntity.class);
        user.setUserCode(userCode);
        user.setUserName(userName);
        user.setUserType(EnumSystemUserType.NORMAL_ADMIN.getCode());
        final String password = generatePassword(6);
        user.setUserPassword(Md5.GetMD5Code(password));
        user.setDefaultPassword(EnumIsDefaultPassword.YES.getCode());
        user.setUserStatus(EnumIsEnable.YES.getCode());
        user.setCreatorName(loginUser.getUserName());
        user.setCreateTime(new Date());
        userDao.insert(user);
    }

    @Override
    public void auth(final String userId, final String rolesStr) {
        String[] roleArray = rolesStr.split(",");
        userDao.batchAuth(userId, roleArray);
    }

    @Override
    public BackendSystemUserDto login(final String code, final String pwd) {
        if (Strings.isNullOrEmpty(code) || Strings.isNullOrEmpty(pwd)) {
            return null;
        }
        String password = Md5.GetMD5Code(pwd);
        SystemUserEntity userEntity = this.userDao.login(code, password);
        return this.generateDto(userEntity);
    }

    @Override
    public BackendSystemUserDto getUserById(final String userId) {
        if (Strings.isNullOrEmpty(userId)) return null;
        SystemUserEntity proxyEntity = ENTITY_FACTORY.generateDBEntity(SystemUserEntity.class);
        proxyEntity.setUserId(Long.valueOf(userId));
        SystemUserEntity userEntity = userDao.unique(proxyEntity);
        return this.generateDto(userEntity);
    }

    private BackendSystemUserDto generateDto(SystemUserEntity userEntity){
        if (null == userEntity) return null;
        BackendSystemUserDto userDto = new BackendSystemUserDto();
        userDto.setUserId(userEntity.getUserId());
        userDto.setUserCode(userEntity.getUserCode());
        userDto.setUserName(userEntity.getUserName());
        userDto.setUserType(userEntity.getUserType());
        return userDto;
    }

    @Override
    public List<FrontFunctionDto> loadUserPrivileges(final Long userId) {
        if (null == userId) return null;
        List<FrontFunctionDto> userFunctions = Lists.newArrayList();
        SystemUserEntity loginUser = this.getLoginUser(userId + "");
        int userType = loginUser.getUserType();
        // system admin has all privileges
        if (EnumSystemUserType.SYSTEM_ADMIN.getCode() == userType){
            userFunctions = functionService.loadAdminPrivileges();
        }else{
            Set<SystemFunctionEntity> userFunctionEntities = userRoleDao.getUserRoles(userId);
            for (SystemFunctionEntity userFunctionEntity : userFunctionEntities) {
                FrontFunctionDto functionDto = new FrontFunctionDto();
                functionDto.setFunctionId(userFunctionEntity.getFunctionId());
                functionDto.setFunctionCode(userFunctionEntity.getFunctionCode());
                functionDto.setFunctionName(userFunctionEntity.getFunctionName());
                functionDto.setFunctionUrl(userFunctionEntity.getFunctionUrl());
                functionDto.setParentId(userFunctionEntity.getParentId());
                userFunctions.add(functionDto);
            }
        }
        return userFunctions;
    }

    /**
     * generate random password()12345
     * @return
     */
    private String generatePassword(final int num){
//        StringBuffer randomPassword = new StringBuffer();
//        String chars = "0123456789";
//        for (int i = 0; i < num; i++) {
//            randomPassword.append(chars.charAt((int) (Math.random() * 10)));
//        }
//        return randomPassword.toString();
        return FrontConstant.DEFAULT_USER_PWD;
    }

    private List<SystemUserDto> generateDtos(List<SystemUserEntity> userList){
        final String datePattern = FrontConstant.DATE_PATTERN_NORMAL;
        List<SystemUserDto> resultList = Lists.newArrayList();
        for (SystemUserEntity systemUser : userList) {
            SystemUserDto userDto = new SystemUserDto();
            userDto.setUserId(systemUser.getUserId());
            userDto.setUserCode(systemUser.getUserCode());
            userDto.setUserName(systemUser.getUserName());
            userDto.setUserStatus(systemUser.getUserStatus());
            userDto.setUserType(systemUser.getUserType());
            userDto.setCreatorName(systemUser.getCreatorName());
            userDto.setCreateTime(DataUtil.formatDate(systemUser.getCreateTime(), datePattern));
            userDto.setModifier(systemUser.getModifier());
            userDto.setModifyTime(DataUtil.formatDate(systemUser.getModifyTime(), datePattern));
            resultList.add(userDto);
        }
        return resultList;
    }
}
